#include <stdio.h>
#include <stdint.h>
#include <rtthread.h>
#include "wn_device.h"
#include "wn_protocol.h"
#include "../emu_common.h"
#include "wn_uart.h"
#include <rtdevice.h>

//1.手机下发wn设备mac 地址 id
//2.将所有设备添加到白名单
//3.如果是第一次下发，通过广播设置id
//4.任务1： 轮询读取寄存器信息，并更新， mqtt 上传
//5.任务2： 响应外部指令，读取和设置相关寄存器

#define PLC_SERIAL "uart1"
serial_t g_wn_serial;
wn_device_t g_wn_devices[WN_DEVICE];

 struct rt_event plc_event;
static rt_uint8_t g_work_status = status_init;

int decicemgr_task(void*data);

void test_get_deivce()
{
    rt_strncpy(g_wn_devices[0].device_sn,"0x01234567",4);
    g_wn_devices[0].enable = 1;
    g_wn_devices[0].device_sn[0] = 1;
    g_work_status = status_add_whitelist;
}
void init_wn_device()
{
    /* 初始化事件对象 */
   int result = rt_event_init(&plc_event, "event", RT_IPC_FLAG_PRIO);
   if (result != RT_EOK)
   {
       rt_kprintf("init event failed.\n");
       return -1;
   }

}
void init_devicemgr_task()
{
    test_get_deivce();
    int ret = wn_plc_init();
    if(ret == -1)
    {
        printf("wn plc serail init failed.\n");
        return;
    }

    //emupack_plc_readDevice
    char outdata[256];
    int datalen = emupack_plc_readDevice(outdata);
    serial_send(&g_wn_serial, outdata, datalen);

    //获取设备信息
    //thread_create("uart_wn_task", 2048, decicemgr_task, NULL);
   rt_thread_t thread = rt_thread_create("devicemgr",decicemgr_task,RT_NULL,2048,25,10);
    /* 创建成功则启动线程 */
   if (thread != RT_NULL)
   {
       rt_thread_startup(thread);
   }
   else
   {
       int ret = RT_ERROR;
   }
   rt_thread_t thread_scan = rt_thread_create("thread_scan",scan_process,RT_NULL,2048,25,10);
       /* 创建成功则启动线程 */
  if (thread_scan != RT_NULL)
  {
      rt_thread_startup(thread_scan);
  }
  else
  {
      int ret = RT_ERROR;
  }
    return;
}
int decicemgr_task(void*data)
{
    // 循环获取设备状态
    while(1)
    {
        //获取
        switch(g_work_status)
        {
        case status_init:
        {
            test_get_deivce();
        }
        break;
        case status_add_whitelist:
        {
            //将所有有效addr 添加白名单
            rt_int8_t devices[WN_DEVICE*6];
            rt_int8_t num = 0;
            for(int i=0;i<WN_DEVICE;i++)
            {
                if(g_wn_devices[i].enable)
                {
                    devices[num*6+0]=g_wn_devices[i].device_sn[0];
                    devices[num*6+1]=g_wn_devices[i].device_sn[1];
                    devices[num*6+2]=g_wn_devices[i].device_sn[2];
                    devices[num*6+3]=g_wn_devices[i].device_sn[3];
                    devices[num*6+4]=g_wn_devices[i].device_sn[4];
                    devices[num*6+5]=g_wn_devices[i].device_sn[5];
                    num++;
                }
            }
            int ret = wn_plc_addWhiteList(devices,num);
            if(ret == EMU_SUCCESS)
                g_work_status = status_broadcost_id;
            else {
                printf("status_add_whitelist failed\n");
            }
        }
        break;
        case status_broadcost_id:
        {
            wn_device_broadcast();
            g_work_status = status_normal;
        }
        break;
        case status_normal:
        {

        }
        break;
        case status_update_wn:
        {

        }
        break;
        }
        rt_thread_delay(1);
    }
}
int scan_process(void*data)
{
    while(1)
    {
        if(g_work_status == status_normal)
            for(int i=0 ;i<WN_DEVICE;i++)
            {
                rt_uint8_t msg[MGS_LEN_MAX];
                if(g_wn_devices[i].enable)
                {
                    //读取系统参数
                    wn_device_readRegs(g_wn_devices[i].id,g_wn_devices[i].device_sn,WN_SYSCONF_ADDR,0x0a);
                    //读取采样参数
                    wn_device_readRegs(g_wn_devices[i].id,g_wn_devices[i].device_sn,WN_SIMPLE_ADDR,0x17);
                }
            }
        rt_thread_delay(1);
    }
}
int frame_check_crc(uint8_t*data,  int len)
{
    return 0;
}
int recv_onepacket(serial_t *serial, uint8_t *recvBuf, uint32_t recvBufLen, uint32_t timeout, uint32_t tryOneDelayMs,uint32_t *sendBufLen)
{

    //读取头部字节
    int want_read = 8;
    int reallen = 0;
    int creadlen = serial_recv(serial,recvBuf,want_read,timeout,tryOneDelayMs,sendBufLen);
    if(creadlen == -1)
    {
        printf("timeout\n");
        return -1;
    }
    // 第7,8 字节为数据长度
    int datalen = recvBuf[6]|(recvBuf[7]<<8);
    want_read = datalen;
    reallen+=creadlen;

    creadlen = serial_recv(serial,recvBuf+reallen,want_read,timeout,tryOneDelayMs,sendBufLen);
    if(creadlen == -1)
    {
        printf("timeout\n");
        return -1;
    }
    //读取crc
    want_read = 2;
    reallen+=creadlen;
    creadlen = serial_recv(serial,recvBuf+reallen,want_read,timeout,tryOneDelayMs,sendBufLen);
    if(creadlen == -1)
    {
        printf("timeout\n");
        return -1;
    }
    reallen+=creadlen;
    return reallen;
}

void handle_wn_reveivedata(uint8_t*data,  int len)
{
    if(len<4)
    {
        return ;
    }
    if(EMU_SUCCESS != frame_check_crc(data,len))
    {
        printf("Error: frame_check_crc\n");
        return;
    }
    wn_frame_head_t* frame_head = data;
    if(frame_head->head == HEAD_WN)
    {
        switch(frame_head->code)
        {
            case 0x03:
            {

            }
            break;
            case 0x06:
            {

            }
            break;     
            case 0x10:
            {

            }
            break;
            case 0x20:
            {

            }
            break;  
            case 0x21:
            {

            }
            break;
            case 0x22:
            {

            }
            break;     
            case 0x24:
            {

            }
            break;
            case 0x25:
            {

            }
            break;  
            case 0x26:
            {

            }
            break;     
            case 0x27:
            {

            }
            break;
            case 0x28:
            {

            }
            break;  
            case 0x30:
            {

            }
            break; 
            default:
            {
                printf("not support code:%d\n",frame_head->code);
            }
            break;     
        }
    }
    else if(frame_head->head == HEAD_PLC)
    {
        wn_plc_frame_head_t* plchead = (wn_plc_frame_head_t*)data;
        switch(plchead->code)
        {
            //case
        };
        rt_event_send(&plc_event, PLC_READDEVICE_RESP_EVENT);
    }
}
rt_uint8_t wn_device_readRegs(uint8_t id,uint8_t* sn,uint16_t startReg,uint16_t regNum)
{
    char outdata[256];
    int datalen = emupacket_read_regs(id,startReg,regNum,outdata);
    wn_plc_transform(sn,outdata,datalen);
    //等待回复
    //分发给mqtt， 修改全局变量
    uint8_t recvData[1024];
    int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
    if(recvlen == -1)
    {
        printf("超时");
    }
    //wn 包长度
    //int datalen = recvData[6]|(recvData[7]<<8);
    //parse_wn_regs();
    rt_uint8_t address[6]={0};
    rt_uint8_t *wn_packet = (recvData+8);
    rt_uint8_t index = 0;
    rt_memcpy(address,wn_packet,6);
    index+=6;
    rt_uint16_t wn_packLen = *(rt_uint16_t*)(wn_packet+index);
    index+=2;
    //wn 包结构
    rt_uint8_t wn_head = wn_packet[index++];
    rt_uint8_t wn_len  = wn_packet[index++];
    rt_uint8_t wn_addr = wn_packet[index++];
    rt_uint8_t wn_cmd = wn_packet[index++];
    rt_uint16_t wn_startRegister = *(rt_uint16_t*)(wn_packet+index);
    index+=2;
    rt_uint16_t wn_registerNum =  *(rt_uint16_t*)(wn_packet+index);
    index+=2;
    wn_device_t* device = wn_getdevice_fromSn(sn);
    for(int i =  0;i<wn_registerNum;i++)
    {
        rt_uint32_t wn_registervalue =  *(rt_uint32_t*)(wn_packet+index);
        index+=4;
        wn_update_field_addr(device,startReg+i*4,wn_registervalue);
    }
    //更新数据
    wn_setdevice_fromSn(device,sn);
    return EMU_SUCCESS;

}
rt_uint8_t wn_device_broadcast()
{
    char outdata[1024];
    int datalen =emupacket_device_basic(0,FC_SET_ID_FRAME,outdata);
    int device_num = 0;
    int devicenum_index = datalen;
    outdata[datalen++]=device_num; //先占位
    for(int i= 0;i<WN_DEVICE;i++)
    {
        if(g_wn_devices[i].enable)
        {
            device_num++;
            outdata[datalen++]=g_wn_devices[i].device_sn[0];
            outdata[datalen++]=g_wn_devices[i].device_sn[1];
            outdata[datalen++]=g_wn_devices[i].device_sn[2];
            outdata[datalen++]=g_wn_devices[i].device_sn[3];
            outdata[datalen++]=g_wn_devices[i].id;
        }
    }
    outdata[devicenum_index]=device_num;
    outdata[1] = datalen+2; //包总长度
    datalen = empack_crc(outdata,datalen); //计算crc
    wn_plc_transform(0xFFFFFFF,outdata,datalen);
    //接受响应
    //uint8_t recvData[1024];
    //int recvlen = recv_onepacket(g_wn_serial,recvData,1024,300,0,NULL);
    //if(recvlen == -1)
    //{
    //   printf("超时");
    //}
    return 0;
}
rt_uint8_t wn_device_writereg(uint8_t* sn,uint16_t startReg,float value)
{
    wn_device_t* device = wn_getdevice_fromSn(sn);
    char outdata[1024];
    uint32_t u32_value = 0;
    rt_strncpy(&u32_value,&value,4);
    int datalen =emupacket_device_basic(device->id,FC_WRITE_REG,outdata);
    outdata[datalen++]=startReg & 0xff;
    outdata[datalen++]=startReg >>8;
    outdata[datalen++]=u32_value & 0xff;
    outdata[datalen++]=u32_value >>8;
    outdata[1] = datalen+2; //包总长度
    datalen = empack_crc(outdata,datalen); //计算crc
    wn_plc_transform(device->device_sn,outdata,datalen);
    //接收响应
    uint8_t recvData[1024];
    int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
    if(recvlen == -1)
    {
       printf("超时");
       return EMU_ERROR;
    }
    //修改全局变量对应值

    return EMU_SUCCESS;
}
rt_uint8_t wn_plc_init()
{
    //初始化串口
     rt_strncpy(g_wn_serial.serialName,PLC_SERIAL,sizeof(PLC_SERIAL));
     g_wn_serial.conf.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
     g_wn_serial.conf.data_bits = DATA_BITS_8;           //数据位 8
     g_wn_serial.conf.stop_bits = STOP_BITS_1;           //停止位 1
     g_wn_serial.conf.bufsz     = 128;                   //修改缓冲区 buff size 为 128
     g_wn_serial.conf.parity    = PARITY_NONE;           //无奇偶校验位
     int ret = serial_open(&g_wn_serial);
     if(ret != RT_EOK)
     {
         printf("open wn serial failed\n");
         return -1;
     }
     /* 初始化事件对象 */
    int result = rt_event_init(&plc_event, "event", RT_IPC_FLAG_PRIO);
    if (result != RT_EOK)
    {
        rt_kprintf("init event failed.\n");
        return -1;
    }
    return 0;
     //读取网络节点
     //初始化节点
     //wn_plc_readNetNodes();
}
wn_device_t* wn_getdevices(wn_device_t*devices,rt_uint32_t* size)
{
    if(devices == NULL || size == NULL)
    {
        return NULL;
    }
    int num =0;
    for(int i= 0;i<WN_DEVICE;i++)
    {
        if(g_wn_devices[i].enable)
        {
             rt_memcpy(g_wn_devices+i,devices+i,sizeof(wn_device_t));
             num++;
        }
    }
    *size = num;
    return devices;
}
wn_device_t* wn_getdevice_fromSn(const char* sn)
{
    for(int i= 0;i<WN_DEVICE;i++)
    {
        if(g_wn_devices[i].enable)
        {
            if(sn == g_wn_devices[i].device_sn)
                return g_wn_devices+i;
        }
    }
    return NULL;
}
void    wn_setdevice_fromSn(wn_device_t* device,const char* sn)
{
    for(int i= 0;i<WN_DEVICE;i++)
    {
        if(g_wn_devices[i].enable)
        {
            if(sn == g_wn_devices[i].device_sn)
                rt_memcpy(g_wn_devices+i,device,sizeof(wn_device_t));
        }
    }
    return;
}

rt_uint8_t wn_device_writeregs(uint8_t* sn,wn_reg_t* regs,uint16_t regNum)
{
    wn_device_t* device = wn_getdevice_fromSn(sn);
    char outdata[1024];
    int datalen =emupacket_device_basic(device->id,FC_WRITE_REGS,outdata);
    rt_uint16_t startReg = regs[0].regStart;
    outdata[datalen++]=startReg & 0xff;
    outdata[datalen++]=startReg >>8;
    outdata[datalen++]=regNum & 0xff;
    outdata[datalen++]=regNum >>8;
    for(int i=0;i<regNum;i++)
    {
        outdata[datalen++]=regs[i].regValue >>24;
        outdata[datalen++]=(regs[i].regValue >>16) & 0xff;
        outdata[datalen++]=(regs[i].regValue >>8) & 0xff;
        outdata[datalen++]=(regs[i].regValue ) & 0xff;
    }

    outdata[1] = datalen+2; //包总长度
    datalen = empack_crc(outdata,datalen); //计算crc
    wn_plc_transform(device->device_sn,outdata,datalen);
    //接收响应
    uint8_t recvData[1024];
    int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
    if(recvlen == -1)
    {
       printf("超时");
       return EMU_ERROR;
    }
    //修改全局变量对应值
    return 0;
}
rt_uint8_t wn_device_readfile_error(uint8_t* sn)
{
    wn_device_t* device = wn_getdevice_fromSn(sn);
    //接收响应
       uint8_t recvData[1024];
       int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
       if(recvlen == -1)
       {
          printf("超时");
          return EMU_ERROR;
       }
       //plc 包
       //wn 包长度
       int datalen = recvData[6]|(recvData[7]<<8);
       //parse_wn_regs();
       rt_uint8_t address[6]={0};
       rt_uint8_t *wn_packet = (recvData+8);
       rt_uint8_t index = 0;
       rt_memcpy(address,wn_packet,6);
       index+=6;
       rt_uint16_t wn_packLen = *(rt_uint16_t*)(wn_packet+index);
       index+=2;
       //wn 包结构
       rt_uint8_t wn_head = wn_packet[index++];
       rt_uint8_t wn_len  = wn_packet[index++];
       rt_uint8_t wn_addr = wn_packet[index++];
       rt_uint8_t wn_cmd = wn_packet[index++];
       rt_uint16_t wn_startRegister = *(rt_uint16_t*)(wn_packet+index);
       index+=2;
       rt_uint16_t wn_registerNum =  *(rt_uint16_t*)(wn_packet+index);
       index+=2;
       for(int i =  0;i<wn_registerNum;i++)
       {
           rt_uint32_t wn_registervalue =  *(rt_uint32_t*)(wn_packet+index);
           index+=4;
           wn_update_field_addr(device,wn_startRegister+i*4,wn_registervalue);
       }
       //更新数据
       wn_setdevice_fromSn(device,sn);
       return EMU_SUCCESS;
}
rt_uint8_t wn_device_startframe(uint8_t* sn,uint8_t file_type,uint32_t filesize,uint16_t packsize)
{
      wn_device_t* device = wn_getdevice_fromSn(sn);
      char outdata[1024];
      int datalen =emupacket_device_basic(device->id,FC_LOAD_STARTFRAME,outdata);
      outdata[datalen++]=file_type;
      outdata[datalen++]=filesize>>24;
      outdata[datalen++]=(filesize >>16) & 0xff;
      outdata[datalen++]=(filesize >>8) & 0xff;
      outdata[datalen++]=(filesize ) & 0xff;
      outdata[datalen++]=packsize & 0xff;
      outdata[datalen++]=packsize >>8;
      outdata[1] = datalen+2; //包总长度
      datalen = empack_crc(outdata,datalen); //计算crc
      wn_plc_transform(device->device_sn,outdata,datalen);
      //接收响应
      uint8_t recvData[1024];
      int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
      if(recvlen == -1)
      {
         printf("超时");
         return EMU_ERROR;
      }
      return EMU_SUCCESS;
      //修改全局变量对应值
}
rt_uint8_t wn_device_dataFrame(uint8_t* sn,uint8_t file_type,uint16_t packetIndex,uint8_t* data,int dataLen)
{
    wn_device_t* device = wn_getdevice_fromSn(sn);
    char outdata[1024];
    int datalen =emupacket_device_basic(device->id,FC_LOAD_DATAFRAME,outdata);
    outdata[datalen++]=file_type;
    outdata[datalen++]=packetIndex & 0xff;
    outdata[datalen++]=packetIndex >>8;
    rt_memcpy(outdata+datalen,data,dataLen);
    datalen+=dataLen;
    outdata[1] = datalen+2; //包总长度
    datalen = empack_crc(outdata,datalen); //计算crc
    wn_plc_transform(device->device_sn,outdata,datalen);
    //接收响应
    uint8_t recvData[1024];
    int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
    if(recvlen == -1)
    {
       printf("超时");
       return EMU_ERROR;
    }
    return EMU_SUCCESS;
    //修改全局变量对应值
}
rt_uint8_t wn_device_stopFrame(uint8_t* sn,uint8_t file_type)
{
    wn_device_t* device = wn_getdevice_fromSn(sn);
    char outdata[1024];
    int datalen =emupacket_device_basic(device->id,FC_LOAD_ENDFRAME,outdata);
    outdata[datalen++]=file_type;
    outdata[1] = datalen+2; //包总长度
    datalen = empack_crc(outdata,datalen); //计算crc
    wn_plc_transform(device->device_sn,outdata,datalen);
    //接收响应
    uint8_t recvData[1024];
    int recvlen = recv_onepacket(&g_wn_serial,recvData,1024,300,0,NULL);
    if(recvlen == -1)
    {
       printf("超时");
       return EMU_ERROR;
    }
    return EMU_SUCCESS;
}





